#!/usr/bin/ruby
class Computer 
  attr_accessor :display, :motherboard
  attr_reader :drives
  
  def initialize(display=:crt, motherboard=Motherboard.new, drives=[])
    @motherboard = motherboard
    @drives = drives
    @display = display
  end
end

class DesktopComputer < Computer
  
end

class LaptopComputer < Computer
  def initialize(motherboard=Motherboard.new, drives=[])
    super(:lcd, motherboard, drives)
  end
end

class CPU
  
end

class BasicCPU < CPU
  
end

class TurboCPU < CPU
  
end

class Motherboard
  attr_accessor :cpu, :memory_size
  
  def initialize(cpu=BasicCPU.new, memory_size=1000)
    @cpu = cpu
    @memory_size = memory_size
  end
end

class Drive
  attr_reader :type, :size, :writable
  
  def initialize(type, size, writable)
    @type, @size, @writable = type, size, writable
  end
end

class LaptopDrive < Drive
  
end

class ComputerBuilder
  attr_reader :computer
  
  def initialize
    @computer = Computer.new
  end
  
  def turbo(has_turbo_cpu=true)
    @computer.motherboard.cpu = TurboCPU.new
  end
  
  def memory_size=(size_in_mb)
    @computer.motherboard.memory_size = size_in_mb
  end
  
  def computer
    raise "Not enough memory" if @computer.motherboard.memory_size < 250
    raise "Too many drives" if @computer.drives.size > 4
    hard_disk = @computer.drives.find { |drive| drive.type == :hard_disk }
    if !hard_disk
      raise "No room to add hard disk" if @computer.drives.size >= 4
      add_hard_disk(100000)
    end
    @computer
  end
  
  def method_missing(name, *args)
    words = name.to_s.split("_")
    return super(name, *args) unless words.shift == "add"
    words.each do |word|
      next if word == "and"
      add_cd if word == "cd"
      add_dvd if word == "dvd"
      add_hard_disk(100000) if word == "harddisk"
      turbo if word == "turbo"
    end
  end
end

class DesktopComputerBuilder < ComputerBuilder
  def initialize
    @computer = DesktopComputer.new
  end
  
  def display=(display)
    @computer.display = display
  end
  
  def add_cd(writable=false)
    @computer.drives << Drive.new(:cd, 760, writable)
  end
  
  def add_dvd(writable=false)
    @computer.drives << Drive.new(:dvd, 4000, writable)
  end
  
  def add_hard_disk(size_in_mb)
    @computer.drives << Drive.new(:hard_disk, size_in_mb, true)
  end
end

class LaptopComputerBuilder < ComputerBuilder
  def initialize
    @computer = LaptopComputer.new
  end
  
  def display=(display)
    raise "Laptop display must be lcd" unless display==:lcd
  end
  
  def add_cd(writable=false)
    @computer.drives << LaptopDrive.new(:cd, 760, writable)
  end
  
  def add_dvd(writable=false)
    @computer.drives << LaptopDrive.new(:dvd, 4000, writable)
  end
  
  def add_hard_disk(size_in_mb)
    @computer.drives << LaptopDrive.new(:hard_disk, size_in_mb, true)
  end
end